namespace TheGunningMan

import Gunningine

//
// BasicSeeker entity class
//
class BasicSeekerEntity(Gunningine.Entity, IDamageable, IDamager):

    //
    // Fields
    //
    _facingThreshold = 1
    
    _health as single = 1
    _attackRange as single = 10
    
    _target as Gunningine.Entity = null
    
    _attackAnim as string = ""
    
    //
    // Properties
    //
    Health as single:
        get: return _health
    
    AttackRange as single:
        get: return _attackRange
    
    //
    // Constructor
    //
    def constructor(name, position, direction, worldState, alignment):
        super(name, position, direction, "Idle", worldState, alignment)
        
        //            State     Enter           Exit            Update              OnSee
        RegisterState("Idle",   Idle_OnEnter,   null,           null,               OnSee)
        RegisterState("Seek",   Seek_OnEnter,   null,           Seek_OnUpdate,      null)
        RegisterState("Attack", Attack_OnEnter, Attack_OnExit,  Attack_OnUpdate,    null)
        
        // Default movement parameters
        self.MoveSpeed = 5
        self.TurnSpeed = 90

    //
    // IDamageable
    //
    virtual def OnHit(source as IDamager):
        _health -= source.DoDamage(self)
        //if _health <= 0:
        //    SetState("die")
        
    //
    // IDamager
    //
    virtual def DoDamage(target as Gunningine.Entity) as single:
        return 10

    //
    // Event handler for when we see a hostile entity.
    //
    virtual def OnSee(targets as (Gunningine.Entity)):
        // For now, we just start hunting the first entity we see.
        SetState("Seek", targets[0])
        
	//
	// Idle state
	//
    virtual def Idle_OnEnter(*args):
        SetModel(args[0] as Gunningine.Model)
        SetAnimation(args[1] as string)
        _target = null    
        
    //
    // Seek state
    //
    virtual def Seek_OnEnter(*args):
        SetAnimation("walk")    
        _target = args[0] as Gunningine.Entity
        
    virtual def Seek_OnUpdate(worldState as Gunningine.WorldState):
    
        // Find the target, and turn towards
        dirToTarget = (_target.Position - self.Position).Normalised()
        if Vector3.AngleBetween(self.Direction, dirToTarget) > _facingThreshold:
            TurnTowards(dirToTarget)

        // Move towards target, or attack if within range.
        if _target.Position.Distance(self.Position) > _attackRange:
            MoveForward()
        else:
            SetState("Attack", _target)
            
    //
    // Attack state
    //
    // The way to do melee attacks is to spawn a stationary
    // projectile with a one-frame lifespan at the point of
    // attack, and treat this as a normal damager.
    //
    
    // Enter
    virtual def Attack_OnEnter(*args):
        SetAnimation(args[0] as string)
        _target = args[1] as Gunningine.Entity
        
    // Update entity
    virtual def Attack_OnUpdate(worldState as WorldState):
        // TODO: wait until they've finished their attack
        // as they can't really stop halfway through.
        if _target.Position.Distance(self.Position) > _attackRange:
            SetState("Seek", _target)

                
    // Exit
    virtual def Attack_OnExit():
        _target = null